#pragma once	

#ifndef Calls_h
#define Calls_h

#include "Standards.h"
#include "StmtTable.h"
#include "VarTable.h"
#include "ProcTable.h"
#include "Schema.h"

/*! Calls Class */
class Calls {
	public:
		StmtTable* myST; //!< StmtTable pointer
		VarTable* myVT; //!< VarTable pointer
		ProcTable* myPT; //!< ProcTable pointer
		unordered_multimap<INDEX, INDEX> callsTableStmt; //!< Calls table
		unordered_multimap<INDEX, INDEX> callsTableStmtClosure; //!< Calls closure table
		
		//! Constructor (takes in the VarTable and stmtTable)
		Calls(VarTable*, StmtTable*, ProcTable*);
		
		/*! 
		  A method that computes and stores the transitive closures
		*/
		void computeClosure();
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls(p1,p2)
		  \param NAME p1
		  \param NAME p2
		*/
		Schema getSynSyn(NAME,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls(p1,"Solo")
		  \param NAME p1
		  \param string "Solo"
		*/
		Schema getSynIdent(NAME,string);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls(s1,_)
		  \param NAME s1
		*/
		Schema getSynUnd(NAME);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls("Solo",p2)
		  \param string "Solo"
		  \param NAME s2
		*/
		Schema getIdentSyn(string,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls("Solo","Duo")
		  \param string "Solo"
		  \param string "Duo"
		*/
		Schema getIdentIdent(string,string);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls("Solo",_)
		  \param string "Solo"
		*/
		Schema getIdentUnd(string);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls(_,3)
		  \param INDEX 3
		*/
		Schema getUndIdent(string);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls(_,s2)
		  \param NAME s2
		*/
		Schema getUndSyn(NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls(_,_) 
		*/
		Schema getUndUnd();
		
		//...Closure...

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*(p1,p2)
		  \param NAME p1
		  \param NAME p2
		*/
		Schema getSynSynClosure(NAME,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*(p1,"Solo")
		  \param NAME p1
		  \param string "Solo"
		*/
		Schema getSynIdentClosure(NAME,string);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*(s1,_)
		  \param NAME s1
		*/
		Schema getSynUndClosure(NAME);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*("Solo",p2)
		  \param string "Solo"
		  \param NAME s2
		*/
		Schema getIdentSynClosure(string,NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*("Solo","Duo")
		  \param string "Solo"
		  \param string "Duo"
		*/
		Schema getIdentIdentClosure(string,string);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*("Solo",_)
		  \param string "Solo"
		*/
		Schema getIdentUndClosure(string);

		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*(_,3)
		  \param INDEX 3
		*/
		Schema getUndIdentClosure(string);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*(_,s2)
		  \param NAME s2
		*/
		Schema getUndSynClosure(NAME);
		
		/*! 
		  A method that returns tuples satisfying the relation with parameters provided such as Calls*(_,_) 
		*/
		Schema getUndUndClosure();

		/*! 
		  A method that inserts tuple <x,y> into Calls table signifying x calls y
		  \param INDEX Follower
		  \param INDEX Followed
		*/
		void set(INDEX, INDEX);

	private:
		int count; //!< Size of Calls table
};

#endif